#![allow(unused_imports)]
#![allow(unused_variables)]

use std::env::var;
use clap::Parser;

use tokio_postgres::{NoTls, Error, Config, SimpleQueryMessage::{Row,CommandComplete} };

#[derive(Parser, Clone)]
struct Opts {
    id: String,
    db_type: String,
    #[clap(short, long)]
    file: Option<String>,
    #[clap(short, long)]
    command: Option<String>,
}
async fn setup_postgres(opts: Opts) -> Result<(), Error> {
    let id = opts.id ;
    let hosts_key = format!("{}_PG_NODES", id) ;
    let hosts = var(&hosts_key).unwrap() ;
    let db_key = format!("{}_PG_DBNAME", id) ;
    let db: String = var(&db_key).unwrap() ;
    let username_key: String = format!("{}_PG_USERNAME", id) ;
    let username: String = var(&username_key).unwrap() ;
    let password_key: String = format!("{}_PG_PASSWORD", id) ;
    let password = var(&password_key).unwrap();


    let host_vec: Vec<&str> = hosts.split(',').collect() ;
    let one_host_part: Vec<&str> = host_vec[0].splitn(2, ':').collect() ;
    let one_host_node: &str = one_host_part[0] ;
    let one_host_port: u16 = one_host_part[1].parse().unwrap() ;
    let mut config_default = Config::default() ;
    let config = config_default.host(one_host_node).port(one_host_port).user(&username).password(&password).dbname(&db) ;
    let (client, connection) =
        config.connect(NoTls).await?;

    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    }) ;

    let mut rows: Option<Vec<tokio_postgres::SimpleQueryMessage>> = None ;
    if opts.command.is_some() {
        rows = Some(client.simple_query(&opts.command.unwrap()).await?) ;
    }
    if opts.file.is_some() {
        let command = tokio::fs::read_to_string(opts.file.unwrap()).await.expect("file read error!") ;
        rows = Some(client.simple_query(&command).await?) ;
    }
    if rows.is_some() {
        println!("{}", rows.unwrap().len()-1) ;
    }
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    dotenv::from_filename("meta-lib-static/env/.env").ok();

    let opts: Opts = Opts::parse();
    let db_type = opts.db_type.clone();

    match db_type.as_str() {
        "postgres" => setup_postgres(opts).await? ,
        _ => unimplemented!()
    }
    Ok(())
}
